﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;

namespace _Sieci_Email_Klient
{
    public partial class SignIn : Form
    {
        string serverIP = "192.168.1.1";
        int serverPort = 1337;
        SignIn obj;

        private delegate void CheckLoginCallback(string message);

        private void CheckLogin(string message)
        {
            if (obj.InvokeRequired)
            {
                CheckLoginCallback check = new CheckLoginCallback(CheckLogin);
                obj.Invoke(check, message);
            }
            else
            {
                if (message == "503")
                {
                    warningLabel.Text = "Incorrect Username or Password";
                }
                else
                {
                    System.Threading.Thread t =
                        new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(newForm));
                    UserData data = new UserData
                                        {
                                            Login = textBox1.Text,
                                            Domain = message,
                                            ServerPort = serverPort,
                                            ServerIp = serverIP
                                        };
                    t.Start(data);
                    Close();
                }
            }
        }
        private void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                /* retrieve the SocketStateObject */
                SocketStateObject state = (SocketStateObject)ar.AsyncState;
                Socket socketFd = state.m_SocketFd;

                /* read data */
                int size = socketFd.EndReceive(ar);

                //if (size > 0)
                //{
                    state.m_StringBuilder.Append(Encoding.ASCII.GetString(state.m_DataBuf, 0, size));

                    /* get the rest of the data */
                    //socketFd.BeginReceive(state.m_DataBuf, 0, SocketStateObject.BUF_SIZE, 0,
                                          //new AsyncCallback(ReceiveCallback), state);
                //}
                //else
                //{
                    /* all the data has arrived */
                    if (state.m_StringBuilder.Length > 1)
                    {
                        string receivedMessage = state.m_StringBuilder.ToString();
                        switch (state.m_cmd)
                        {
                            case Command.Login:
                                CheckLogin(state.m_StringBuilder.ToString());
                                break;

                        }
                        /* shutdown and close socket */
                        socketFd.Shutdown(SocketShutdown.Both);
                        socketFd.Close();
                    }
                //}
            }
            catch (Exception exc)
            {
                MessageBox.Show("Exception:\t\n" + exc.Message.ToString());
            }
        }

        private void SendCallBack(IAsyncResult ar)
        {
            SocketStateObject state = (SocketStateObject)ar.AsyncState;
            Socket socketFd = state.m_SocketFd;
            socketFd.EndSend(ar);

            /* create the SocketStateObject */
            
            state.m_SocketFd = socketFd;

            /* begin receiving the data */
            state.m_SocketFd.BeginReceive(state.m_DataBuf, 0, SocketStateObject.BUF_SIZE, 0,
                                 new AsyncCallback(ReceiveCallback), state);
        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                /* retrieve the socket from the state object */
                SocketStateObject state = (SocketStateObject)ar.AsyncState;

                Socket socketFd = state.m_SocketFd;
                /* complete the connection */
                socketFd.EndConnect(ar);

                /* create the SocketStateObject */

                state.m_SocketFd = socketFd;
                byte[] bMessage = Encoding.ASCII.GetBytes(state.m_Message);

                state.m_SocketFd.BeginSend(bMessage, 0, sizeof(byte) * bMessage.Length, 0, new AsyncCallback(SendCallBack), state);

            }
            catch (SocketException ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
            catch (Exception exc)
            {
                MessageBox.Show("Exception:\t\n" + exc.StackTrace);
            }
        }

        private void GetHostEntryCallback(IAsyncResult ar)
        {
            try
            {
                IPHostEntry hostEntry = null;
                IPAddress[] addresses = null;
                Socket socketFd = null;
                IPEndPoint endPoint = null;

                /* complete the DNS query */
                hostEntry = Dns.EndGetHostEntry(ar);
                addresses = hostEntry.AddressList;

                /* create a socket */
                socketFd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                SocketStateObject state = (SocketStateObject)ar.AsyncState;

                state.m_SocketFd = socketFd;

                /* remote endpoint for the socket */
                endPoint = new IPEndPoint(addresses[0], Int32.Parse(serverPort.ToString()));

                /* connect to the server */
                state.m_SocketFd.BeginConnect(endPoint, new AsyncCallback(ConnectCallback), state);
            }
            catch (Exception exc)
            {
                MessageBox.Show("Exception:\t\n" + exc.Message.ToString());
            }
        }

        private void ConnectToServer()
        {
            //try
            //{
            //    clientSocket = new TcpClient();
            //    clientSocket.Connect(serverIP, serverPort);
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show(ex.Message);
            //}
        }

        private void SendMessage(string message, Command cmd)
        {
            try
            {
                //serverStream = clientSocket.GetStream();
                //byte[] outStream = Encoding.ASCII.GetBytes(message);
                //serverStream.Write(outStream, 0, outStream.Length);
                ////serverStream.Flush();
                //
                bool abort = false;
                SocketStateObject state = new SocketStateObject();
                state.m_Message = message;
                state.m_cmd = cmd;
                if(textBox3.Text != "")
                {
                    serverIP = textBox3.Text;
                }
                else
                {
                    serverIP = "192.168.1.1";
                }
                try
                {
                    serverPort = Convert.ToInt32(textBox4.Text);
                }
                catch(FormatException ex)
                {
                    DialogResult result = MessageBox.Show("Invalid Port. Do you want to use the default 1337 port?", "Invalid Port", MessageBoxButtons.YesNo);
                    if (result == DialogResult.Yes)
                    {
                        serverPort = 1337;
                    }
                    else
                    {
                        abort = true;
                    }
                }
                if(!abort)
                {
                    Dns.BeginGetHostEntry(serverIP, new AsyncCallback(GetHostEntryCallback), state);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        public string ReceiveMessage()
        {
            //try
            //{
            //    //serverStream = new NetworkStream(clientSocket);

            //    string msg = "";
            //    byte[] inStream = new byte[1];
            //    bool quit = false;
            //    while (!quit)
            //    {
            //        int n = serverStream.Read(inStream, 0, 1);
            //        if (inStream[0] == Convert.ToByte('\0'))
            //        {
            //            quit = true;
            //            break;
            //        }
            //        msg += Encoding.ASCII.GetString(inStream);
            //    }
            //    //string returnData = Encoding.ASCII.GetString(inStream);
            //    string returnData = msg;
            //    return returnData;
            //}
            //catch (Exception ex)
            //{
            //    MessageBox.Show(ex.Message);
            //}
            return null;
        }

        public SignIn()
        {
            InitializeComponent();
            obj = this;
        }

        private void newForm(object text)
        {
            Application.Run(new Inbox((UserData)text));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                string message = "helo#" + textBox1.Text + "#" + textBox2.Text + "#";
                SendMessage(message, Command.Login);
            }
            catch (Exception ex)
            {
                return;
                MessageBox.Show(ex.Message);
            }
        }


    }
}
